/*
 * @Author: Await
 * @Date: 2025-05-10 17:20:00
 * @LastEditors: Await
 * @LastEditTime: 2025-05-07 15:34:47
 * @Description: Lines3D调试工具与数据处理
 */

import { DataItem } from '../../types/dataTypes';

/**
 * 验证lines3D格式数据
 * 确保数据格式为三层嵌套数组[[[x,y,z], ...], ...] 
 * @param data 要验证的数据
 * @returns 验证结果或修复后的数据
 */
export const validateLines3DData = (data: any): any => {
    // 先检查数据格式
    const validationResult = checkDataFormat(data);
    console.log('Lines3D数据验证结果:', validationResult);

    if (!validationResult.valid) {
        console.warn(`Lines3D数据格式不正确: ${validationResult.format}, 使用默认数据`);
        return createDefaultData();
    }

    // 数据格式正确或基本正确，进行处理和修复
    return processAndFixData(data);
};

/**
 * 检查数据格式是否符合lines3D要求
 */
const checkDataFormat = (data: any): { valid: boolean; nestingLevel: number; format: string } => {
    if (!data || !Array.isArray(data)) {
        return { valid: false, nestingLevel: 0, format: 'invalid-not-array' };
    }

    // 空数组算作有效，但需要标记
    if (data.length === 0) {
        return { valid: true, nestingLevel: 1, format: 'empty-array' };
    }

    // 检查第一层：线段集合
    if (!Array.isArray(data[0])) {
        return { valid: false, nestingLevel: 1, format: 'first-level-not-array' };
    }

    // 空线段集合也算作有效
    if (data[0].length === 0) {
        return { valid: true, nestingLevel: 2, format: 'empty-lines' };
    }

    // 检查第二层：单条线的点
    if (!Array.isArray(data[0][0])) {
        return { valid: false, nestingLevel: 2, format: 'second-level-not-array' };
    }

    // 检查第三层：点的坐标
    const coords = data[0][0];
    if (coords.length < 3 ||
        typeof coords[0] !== 'number' ||
        typeof coords[1] !== 'number' ||
        typeof coords[2] !== 'number') {
        return { valid: false, nestingLevel: 3, format: 'invalid-coordinates' };
    }

    // 通过所有检查，数据格式有效
    return { valid: true, nestingLevel: 3, format: 'valid-lines3d' };
};

/**
 * 处理并修复数据，确保符合lines3D格式
 */
const processAndFixData = (data: any): number[][][] => {
    try {
        // 检查数据嵌套深度
        let nestingLevel = getArrayNestingLevel(data);
        console.log(`Lines3D数据嵌套级别: ${nestingLevel}`);

        // 处理为标准格式
        let standardData: number[][][] = [];

        // 根据嵌套级别处理
        if (nestingLevel === 3) {
            // 已有三层嵌套，但需要验证并确保每个点都有效
            standardData = processThreeLayerData(data);
        } else if (nestingLevel === 2) {
            // 两层嵌套，作为一条线处理
            standardData = [processPointsArray(data)];
        } else if (nestingLevel === 1) {
            // 一层嵌套，可能是单个点或简单值
            if (data.length >= 3 && typeof data[0] === 'number') {
                // 单点，包装成一条只有一个点的线
                standardData = [[processPoint(data)]];
            } else {
                // 假设是点列表，转换为一条线
                standardData = [processPointsArray(data.map((item: any) =>
                    Array.isArray(item) ? item : [item, 0, 0]
                ))];
            }
        } else {
            console.error('Lines3D数据格式错误: 嵌套级别异常');
            return createDefaultData();
        }

        // 最终验证
        if (standardData.length === 0 || standardData[0].length === 0) {
            console.error('Lines3D数据格式错误: 处理后数据为空');
            return createDefaultData();
        }

        // 确保每条线至少有2个点
        standardData = standardData.map(line => {
            if (line.length < 2) {
                // 如果线只有一个点，复制该点形成有效的线段
                const point = line[0] || [0, 0, 0];
                return [point, [point[0] + 1, point[1], point[2]]];
            }
            return line;
        });

        // 过滤掉任何无效点
        standardData = standardData.map(line => {
            return line.filter(point =>
                Array.isArray(point) && point.length >= 3 &&
                !isNaN(point[0]) && !isNaN(point[1]) && !isNaN(point[2])
            );
        }).filter(line => line.length >= 2); // 每条线至少需要2个点

        // 如果过滤后没有有效线，则使用默认数据
        if (standardData.length === 0) {
            console.error('Lines3D数据格式错误: 过滤后没有有效线');
            return createDefaultData();
        }

        // 确保点坐标是有效数值 
        standardData = standardData.map(line => {
            return line.map(point => {
                return [
                    Number.isFinite(point[0]) ? point[0] : 0,
                    Number.isFinite(point[1]) ? point[1] : 0,
                    Number.isFinite(point[2]) ? point[2] : 0
                ];
            });
        });

        console.log('Lines3D数据格式验证通过:',
            `外层长度=${standardData.length}`,
            `中层长度=${standardData[0].length}`,
            `维度=${standardData[0][0].length}`
        );

        return standardData;
    } catch (error) {
        console.error('Lines3D数据格式验证出错:', error);
        return createDefaultData();
    }
};

/**
 * 确定数组的嵌套级别
 * @param arr 要检查的数组
 * @returns 嵌套级别 (0-3)
 */
function getArrayNestingLevel(arr: any): number {
    if (!Array.isArray(arr)) return 0;
    if (arr.length === 0) return 1;

    // 检查第一个元素，确保不会出现异常
    try {
        let level = 1;
        let current = arr;

        // 检查最多三层
        while (Array.isArray(current) && current.length > 0 && Array.isArray(current[0])) {
            level++;
            current = current[0];
            // 对于lines3D，我们最多关心3层
            if (level >= 3) break;
        }

        return level;
    } catch (error) {
        console.error('检查数组嵌套级别出错:', error);
        return 1; // 默认为一层
    }
}

/**
 * 处理三层嵌套数据
 * @param data 三层嵌套数组
 * @returns 规范化的三层嵌套数组
 */
function processThreeLayerData(data: any[]): number[][][] {
    try {
        // 过滤和转换每条线
        return data.filter(line => Array.isArray(line) && line.length > 0)
            .map(line => {
                if (!Array.isArray(line)) return [[0, 0, 0], [1, 0, 0]];
                return processPointsArray(line);
            });
    } catch (error) {
        console.error('处理三层嵌套数据出错:', error);
        // 返回至少一条有效线段
        return [[[0, 0, 0], [1, 1, 1]]];
    }
}

/**
 * 处理点数组(线)
 * @param points 点数组
 * @returns 规范化的点数组
 */
function processPointsArray(points: any[]): number[][] {
    try {
        if (!Array.isArray(points)) return [[0, 0, 0], [1, 0, 0]];
        if (points.length === 0) return [[0, 0, 0], [1, 0, 0]];

        // 处理每个点
        const processedPoints = points.map(point => processPoint(point))
            .filter(point => !isNaN(point[0]) && !isNaN(point[1]) && !isNaN(point[2])); // 过滤无效点

        // 确保至少有两个点
        if (processedPoints.length === 0) {
            return [[0, 0, 0], [1, 0, 0]];
        } else if (processedPoints.length === 1) {
            const p = processedPoints[0];
            processedPoints.push([p[0] + 1, p[1], p[2]]);
        }

        return processedPoints;
    } catch (error) {
        console.error('处理点数组出错:', error);
        // 返回一个简单有效的线段
        return [[0, 0, 0], [1, 1, 1]];
    }
}

/**
 * 处理单个点，确保是[x,y,z]格式
 * @param point 输入点数据
 * @returns 规范化的[x,y,z]坐标
 */
function processPoint(point: any): number[] {
    try {
        if (!point) return [0, 0, 0];

        // 如果是数组且长度>=3，确保是数值
        if (Array.isArray(point) && point.length >= 3) {
            return [
                parseFloat(point[0]) || 0,
                parseFloat(point[1]) || 0,
                parseFloat(point[2]) || 0
            ];
        }

        // 如果是包含x,y,z属性的对象
        if (typeof point === 'object' && point !== null) {
            const x = parseFloat(point.x || point.X || point[0] || 0);
            const y = parseFloat(point.y || point.Y || point[1] || 0);
            const z = parseFloat(point.z || point.Z || point[2] || 0);
            return [x, y, z];
        }

        // 其他情况返回原点
        return [0, 0, 0];
    } catch (error) {
        console.error('处理点数据出错:', error);
        return [0, 0, 0]; // 返回原点
    }
}

/**
 * 创建默认测试数据
 * @returns 测试数据
 */
export const createDefaultData = (): number[][][] => {
    // 创建螺旋线和立方体
    const spiral = [];
    for (let t = 0; t < 10; t += 0.1) {
        const x = Math.cos(t) * t * 0.2;
        const y = Math.sin(t) * t * 0.2;
        const z = t * 0.2;
        spiral.push([x, y, z]);
    }

    const cube = [
        [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], [0, 0, 0],
        [0, 0, 1], [1, 0, 1], [1, 1, 1], [0, 1, 1], [0, 0, 1]
    ];

    // 返回两条线
    return [spiral, cube];
};

/**
 * 创建螺旋线测试数据
 * @returns 螺旋线数据
 */
export const createSpiralData = (): number[][][] => {
    const spiral = [];
    for (let t = 0; t < 10; t += 0.1) {
        const x = Math.cos(t) * t * 0.2;
        const y = Math.sin(t) * t * 0.2;
        const z = t * 0.2;
        spiral.push([x, y, z]);
    }
    return [spiral];
};

/**
 * 创建立方体测试数据
 * @returns 立方体数据
 */
export const createCubeData = (): number[][][] => {
    const cube = [
        // 底面
        [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], [0, 0, 0],
        // 连接底面到顶面
        [0, 0, 1],
        // 顶面
        [1, 0, 1], [1, 1, 1], [0, 1, 1], [0, 0, 1],
        // 连接其他边
        [0, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 1, 1], [1, 0, 1], [1, 0, 0]
    ];
    return [cube];
};

/**
 * 将DataItem数组转换为lines3D格式
 * @param data 原始数据
 * @returns lines3D格式数据
 */
export const convertDataToLines3D = (data: DataItem[]): number[][][] => {
    if (!data || data.length === 0) {
        return createDefaultData();
    }

    try {
        // 尝试将数据转换为lines3D格式
        const points: number[][] = data.map(item => {
            // 尝试提取x, y, z坐标
            const x = parseFloat(String(item.x || item.X || item.value?.[0] || 0));
            const y = parseFloat(String(item.y || item.Y || item.value?.[1] || 0));
            const z = parseFloat(String(item.z || item.Z || item.value?.[2] || 0));

            return [x, y, z];
        });

        // 过滤掉无效点
        const validPoints = points.filter(point =>
            !isNaN(point[0]) && !isNaN(point[1]) && !isNaN(point[2])
        );

        if (validPoints.length < 2) {
            console.log('有效点数不足，使用默认数据');
            return createDefaultData();
        }

        // 将所有点作为一条线返回
        return [validPoints];
    } catch (error) {
        console.error('转换数据到lines3D格式失败:', error);
        return createDefaultData();
    }
};